/*
 * Copyright (C) 2000-2008 Jens Nixdorf and various contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies of the Software, its documentation and marketing & publicity
 * materials, and acknowledgment shall be given in the documentation, materials
 * and software packages that this Software was used.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package org.mopore.jat.board;

import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;

public class BoardAdapter implements KeyListener, MouseListener, MouseMotionListener,
        MouseWheelListener {

    private final IScreenOperator screenOperator;

    private final ICutable cutable;

    private Cutout cutout;

    private Point origin;

    private Marking marking;

    private IMarkable markable;

    private MarkingQueue markingQueue;

    private ButtonBarPainter buttonBarPainter;

    private boolean leftPressed;

    private MouseStrokePreview mouseStrokePreview;

    public BoardAdapter(IScreenOperator screenOperator, ICutable cutable, IMarkable markable,
            MarkingQueue queue, ButtonBarPainter buttonBarPainter,
            MouseStrokePreview mouseStrokePreview) {
        this.screenOperator = screenOperator;
        this.cutable = cutable;
        this.cutout = null;
        this.marking = null;
        this.markable = markable;
        this.markingQueue = queue;
        this.buttonBarPainter = buttonBarPainter;
        this.leftPressed = false;
        this.mouseStrokePreview = mouseStrokePreview;
    }

    public void mousePressed(MouseEvent evt) {

        Point point = evt.getPoint();
        boolean left = (evt.getButton() == MouseEvent.BUTTON1);
        this.leftPressed = left;
        boolean right = (evt.getButton() == MouseEvent.BUTTON3);

        if (left) {
            if (this.buttonBarPainter.handleMouseClickEvent(evt)) {
                screenOperator.setOperating(true);
                return;
            }
            this.markingQueue.setAccessable(false);
            this.marking = new Marking(point,
                    this.buttonBarPainter.getCurrentMarkingColor(), this.buttonBarPainter
                            .getCurrentSize());
            markable.mark(marking);
        }

        if (right) {
            this.cutout = new Cutout();
            int x = evt.getX();
            int y = evt.getY();
            cutout.setX(x);
            cutout.setY(y);
            cutout.setWidth(0);
            cutout.setHeight(0);
            origin = point;
            cutable.cut(cutout);
        }

        screenOperator.setOperating(true);
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent)
     */
    public void mouseDragged(MouseEvent evt) {
        boolean right = (cutout != null);

        if (this.leftPressed) {
            if (this.buttonBarPainter.handleMouseDraggedEvent(evt))
                return;
            if (marking != null) {
                Point point = evt.getPoint();
                marking.add(point);
            }
        }

        if (right) {
            int newX = evt.getX();
            int width;
            if (newX > origin.getX()) {
                width = (int) (newX - origin.getX());
                cutout.setWidth(width);
            }
            if (newX < origin.getX()) {
                width = (int) (origin.getX() - newX);
                cutout.setWidth(width);
                cutout.setX(newX);
            }

            int newY = evt.getY();
            int height;
            if (newY > origin.getY()) {
                height = (int) (newY - origin.getY());
                cutout.setHeight(height);
            }
            if (newY < origin.getY()) {
                height = (int) (origin.getY() - newY);
                cutout.setHeight(height);
                cutout.setY(newY);
            }
            cutable.cut(cutout);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
     */
    public void mouseReleased(MouseEvent evt) {
        this.leftPressed = false;
        boolean left = (evt.getButton() == MouseEvent.BUTTON1);
        boolean right = (evt.getButton() == MouseEvent.BUTTON3);

        if (left) {
            if (this.buttonBarPainter.handleMouseReleasedEvent(evt)) {
                screenOperator.setOperating(false);
                return;
            }
            markable.finishMarking();
            this.markingQueue.setAccessable(true);
            marking = null;
        }

        if (right) {
            cutable.finishCutting();
            cutout = null;
        }
        screenOperator.setOperating(false);
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent)
     */
    public void keyPressed(KeyEvent e) {
        if (this.markingQueue.isAccessable()) {
            if (e.isControlDown() && e.getKeyCode() == KeyEvent.VK_Z)
                this.markingQueue.undo();
            if (e.isControlDown() && e.getKeyCode() == KeyEvent.VK_Y)
                this.markingQueue.redo();
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent)
     */
    public void keyReleased(KeyEvent e) {
    	// adapter dummy 
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent)
     */
    public void keyTyped(KeyEvent e) {
    	// adapter dummy    	
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
     */
    public void mouseClicked(MouseEvent e) {
    	// adapter dummy    	
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
     */
    public void mouseEntered(MouseEvent e) {
    	// adapter dummy    	
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
     */
    public void mouseExited(MouseEvent e) {
    	// adapter dummy    	
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent)
     */
    public void mouseMoved(MouseEvent e) {
        this.buttonBarPainter.handleMouseMovedEvent(e);
        this.mouseStrokePreview.mouseMoved(e);
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.awt.event.MouseWheelListener#mouseWheelMoved(java.awt.event.MouseWheelEvent)
     */
    public void mouseWheelMoved(MouseWheelEvent e) {
        if (e.getWheelRotation() < 0)
            this.buttonBarPainter.biggerStroke();
        else
            this.buttonBarPainter.smallerStroke();
        this.mouseStrokePreview.setNewStroke(new Marking(e.getPoint(), this.buttonBarPainter.getCurrentMarkingColor(),
                this.buttonBarPainter.getCurrentSize()), e.getPoint());
    }
}
